import SftpClient from "ssh2-sftp-client";
import path from "path";
import fs from "fs";
const sftp = new SftpClient();

async function deleteDirectoryRecursively(
	serverPath: string,
	exclude: string[]
) {
	try {
		// 获取目录内容
		const list = await sftp.list(serverPath);
		// 遍历目录内容
		for (const item of list) {
			if (exclude.includes(item.name)) {
				continue;
			}
			const itemPath = `${serverPath}/${item.name}`;
			if (item.type === "d") {
				// 如果是目录，递归删除
				await deleteDirectoryRecursively(itemPath, exclude);
				// 删除空目录
				await sftp.rmdir(itemPath);
				console.log(`删除目录: ${itemPath}`);
			} else {
				// 如果是文件，直接删除
				if (exclude.includes(item.name)) {
					continue;
				}
				await sftp.delete(itemPath);
				console.log(`删除文件: ${itemPath}`);
			}
		}
	} catch (err) {
		console.error(err);
	} finally {
	}
}

async function uploadDirectory(
	localPath: string,
	serverPath: string,
	exclude: string[]
) {
	// 确保目标服务器路径存在
	await sftp.mkdir(serverPath, true);

	const items = fs
		.readdirSync(localPath)
		.filter((item) => !exclude.includes(item))
		.map((r) => path.resolve(localPath, r));

	for (const item of items) {
		let stat = fs.statSync(item);
		const remotePath = serverPath + "/" + path.basename(item); // 生成远程路径

		if (stat.isFile()) {
			// 上传文件
			await sftp.put(item, remotePath);
			console.log(`文件上传成功: ${item} -> ${remotePath}`);
		} else if (stat.isDirectory()) {
			// 递归上传子目录
			await uploadDirectory(item, remotePath, exclude);
			console.log(`目录上传成功: ${item}`);
		}
	}
}
async function release(params: {
	localPath: string;
	serverPath: string;
	exclude: string[];
	serverConfig: {
		host: string;
		port: string; // SFTP 默认端口
		username: string;
		password: string;
	};
}) {
	try {
		await sftp.connect(params.serverConfig);
		console.log(`连接${params.serverConfig.host}成功`);
		await deleteDirectoryRecursively(params.serverPath, params.exclude);
		await uploadDirectory(params.localPath, params.serverPath, params.exclude);
	} catch (err) {
		console.error(err);
	} finally {
		await sftp.end();
	}
}
export default release;
